package nl.weeaboo.sh.danmaku;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

/** Minimal linked list implementation for use in collision grid. The built-in
 *  Java linked list doesn't give access to the list node objects. */
public class ColList implements List<ColNode> {

	ColNode first;
	ColNode last;
	int size;
	
	public ColList() {		
	}
		
	//Functions
	@Override
	public boolean add(ColNode e) {
		if (last == null) {
			first = last = e;
		} else {
			last.next = e;
			e.prev = last;
			last = e;
		}
		e.list = this;
		
		size++;
		return true;
	}

	@Override
	public void add(int index, ColNode element) {
		ColNode c = get(index);		
		c.append(element);
	}

	@Override
	public boolean addAll(Collection<? extends ColNode> c) {
		for (ColNode node : c) {
			add(node);
		}
		return true;
	}

	@Override
	public boolean addAll(int index, Collection<? extends ColNode> c) {
		ColNode current = get(index);
		for (ColNode newNode : c) {
			current.append(newNode);
			current = newNode;
		}
		return true;
	}

	@Override
	public boolean remove(Object o) {
		if (o instanceof ColNode) {
			((ColNode)o).remove();
			return true;
		}
		return false;
	}

	@Override
	public ColNode remove(int index) {
		ColNode node = get(index);
		node.remove();
		return node;
	}

	@Override
	public boolean removeAll(Collection<?> c) {
		for (Object o : c) {
			remove(o);
		}
		return true;
	}

	@Override
	public boolean retainAll(Collection<?> c) {
		ColNode current = first;
		while (current != null) {
			ColNode next = current.next;
			if (!c.contains(current)) current.remove();
			current = next;
		}
		return false;
	}
	
	@Override
	public void clear() {
		ColNode current = first;
		while (current != null) {
			current.list = null;
			current = current.next;
		}
		first = last = null;
	}
	
	@Override
	public ColNode set(int index, ColNode element) {
		ColNode old = get(index);
		old.replace(element);
		return old;
	}

	@Override 
	public List<ColNode> subList(int fromIndex, int toIndex) {
		throw new UnsupportedOperationException();
	}
	
	@Override
	public Iterator<ColNode> iterator() {
		return listIterator();
	}

	@Override
	public ListIterator<ColNode> listIterator() {
		return listIterator(0);
	}
	
	@Override
	public ListIterator<ColNode> listIterator(final int index) {
		return new ListIterator<ColNode>() {
			ColNode current = get(index);
			int t = index;
			
			public boolean hasPrevious() {
				return current != null && current.prev != null;
			}
			public boolean hasNext() {
				return current != null && current.next != null;
			}
			public void remove() {
				ColNode newCurrent = current.next;
				current.remove();
				current = (newCurrent != null ? newCurrent : last);
			}
			public void add(ColNode e) {
				current.append(e);
			}
			public int previousIndex() {
				return t-1;
			}
			public int nextIndex() {
				return t+1;
			}
			public ColNode previous() {
				t--;
				return current.prev;
			}
			public ColNode next() {
				t++;
				return current.next;
			}
			public void set(ColNode e) {
				current.replace(e);
			}			
		};
	}
	
	@Override
	public Object[] toArray() {
		throw new UnsupportedOperationException();
	}

	@Override
	public <T> T[] toArray(T[] a) {
		throw new UnsupportedOperationException();
	}

	//Getters
	@Override
	public boolean contains(Object o) {
		ColNode current = first;
		while (current != null) {
			if (current == o) return true;
			current = current.next;
		}
		return false;
	}

	@Override
	public boolean containsAll(Collection<?> c) {
		for (Object o : c) {
			if (!contains(o)) return false;
		}
		return true;
	}

	@Override
	public ColNode get(int index) {
		if (index < 0 || index >= size) {
			throw new IndexOutOfBoundsException();			
		}
		
		int t = 0;		
		ColNode current = first;
		while (current != null && current.next != null && t < index) {
			current = current.next;
			t++;
		}
		
		return current;
	}

	@Override
	public int indexOf(Object o) {
		int t = 0;
		ColNode current = first;
		while (current != null) {
			if (current == o) return t;
			current = current.next;
			t++;
		}
		return -1;
	}

	@Override
	public int lastIndexOf(Object o) {
		int t = size-1;
		ColNode current = last;
		while (current != null) {
			if (current == o) return t;
			current = current.prev;
			t--;
		}
		return -1;
	}
	
	@Override
	public boolean isEmpty() {
		return first == null;
	}

	@Override
	public int size() {
		return size;
	}
	
	//Setters
	
}
